using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;

namespace IQIGame.Onigao.Logic
{
    /// <summary>
    /// 生成实体
    /// 参数：args1：1：id（实体配置id（为0代表自己）或预设配置id），2：交互类型，3：position.x，4：position.y（不确定可填0），5：position.z，6：是否生成到玩家身边（1：是，0：否，注意该参数与4，5，6号参数互斥），7：rotationY
    /// 参数：args2：tags（可选）
    /// </summary>
    public class ExecGenerateEntity : BaseServiceExecution
    {
        public override void Execute(LevelRegion region, LevelPlayer player)
        {
            var config = _config as ExecParamGenerateEntity;
            int mcid = config.configID;
            if (mcid == 0 && triggerEntity != null)
            {
                mcid = triggerEntity.entityConfig.id;
            }
            if (mcid == 0)
            {
                LogicLog.LogError("参数非法，实体配置id为0。");
                return;
            }
            if (!region.gameplayConfig.entityMap.TryGetValue(mcid, out var entityCfg))
            {
                LogicLog.LogError($"地区配置里找不到mcid：{mcid}。");
                return;
            }

            var initData = new LevelEntityCtorData(entityCfg);
            //交互类型，如果填-1则沿用原配置数据
            if (config.interactType >= 0)
            {
                initData.interactType = (byte)config.interactType;
            }
            //旋转
            initData.initDirEuler = new Vector3Int(0, config.rotationY, 0);
            //计算实体位置
            Vector3Int position;
            if (config.bornNearPlayer) //在英雄附近找合适的点来作为实体出生点
            {
                int radius = LgLevelConst.GenEntityFromHero;
                if (radius >= 300) //厘米
                {
                    //通过寻路api按圆随机查找不精确，底层的逻辑是在圆覆盖的所有网格内随机，也就是说随机范围并不是标准的圆
                    //如果范围太小结果非常不准确，所以仅在随机距离足够大时使用该api
                    region.terrain.FindRandomPointAroundCircle(player.entity.position, radius, out var realPos);
                    position = realPos;
                }
                else //距离太小自行计算随机，再通过寻路api找到里随机位置最近的合法点
                {
                    Vector3Logic floatPos = Vector3Logic.zero;
                    for (int i = 0; i < 4; i++) //4个方向
                    {
                        Vector3Logic dir = GetDirByIndex(i);
                        floatPos = player.entity.position + dir * radius;
                        if (region.terrain.FindNearestPoint(floatPos, out var realEndPos, 50))
                        {
                            floatPos = realEndPos;
                            break;
                        }
                    }
                    position = floatPos;
                }
            }
            else //配置直接指定坐标
            {
                position = config.pos;
            }
            initData.position = position;
            //tag
            ushort[] tags = new ushort[config.tags.Count];
            int index = 0;
            for (int i = 0; i < config.tags.Count; i++)
            {
                tags[index] = config.tags[i];
                index++;
            }
            initData.tags = tags;

            //创建实体
            LevelEntity entity = region.CreateEntity(region.level.AllocateId(),
                initData, true, true);
            region.UpdateEntity(player, entity);
        }

        /// <summary>
        /// 根据方向索引获取方向
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        private Vector3Logic GetDirByIndex(int index)
        {
            switch (index)
            {
                case 0:
                    return Vector3Logic.forward;
                case 1:
                    return Vector3Logic.right;
                case 2:
                    return Vector3Logic.back;
                case 3:
                    return Vector3Logic.down;
                default:
                    return Vector3Logic.forward;
            }
        }
    }
}
